﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using EMC;
using System.Reflection;
using System.Threading;

namespace Server
{
    class FileHandler
    {
        private Socket clientSocket;
        //private string downloadTo;
        private int bufferSize;
        private string[] action;
        private byte[] buffer;
        private FileManagement fileMan;
        private Dictionary<string, string> options;
        //private string mess;

        public FileHandler(Socket clientsock, Dictionary<string, string> Options)
        {
            options = Options;
            clientSocket = clientsock;
            bufferSize = 8192;
            buffer = new byte[bufferSize];
            string dbConfigFile = @"./db_settings.xml";
            databaseConfiguration config = new databaseConfiguration(dbConfigFile);
            fileMan = new FileManagement(config);
        }

        public void handleFile(string[] message)
        {
            System.Diagnostics.Debug.WriteLine("File Message: " + message[0]);
            //string ret = null;
            //Dictionary<string, string> fileDictionary = convertProcotcolToDictionary(message);

            if (message[2] == "UPLOAD")
            {
                //sendMessage(clientSocket,"$FRANK,FILE,UPLOAD,START,");
                data(message);
                //sendMessage(clientSocket,"$FRANK,FILE,UPLOAD,END,");
                //fileMan.addfile(fileDictionary["NAME"], fileDictionary["DESC"], fileDictionary["USER"]);

            }
            else if (message[2] == "DOWNLOAD")
            {
                //   sendMessage(clientSocket,"$FRANK,FILE,DOWNLOAD,START,");
                //data(message);
                DownloadData(message[3]);
                //  sendMessage(clientSocket, "$FRANK,FILE,DOWNLOAD,END,");

            }
            //return ret;
        }

        private void DownloadData(string Filename)
        {

            Message ProtocolMessage = new Message();
            FileInfo fileinfo = new FileInfo(options["Projects_Path"] + Filename);

            int TotalNumberOfPackets = (int)Math.Round((double)fileinfo.Length / (long)bufferSize);

            ProtocolMessage.sendMessage(clientSocket, "$FRANK,DOWNLOAD," + TotalNumberOfPackets + ",");

            if (ProtocolMessage.recMess(clientSocket) == "$FRANK,DOWNLOAD,OK")
            {
                long TempLengthOfFile = fileinfo.Length;
                long TotalBytesSent = 0;
                long PacketNumber = 0;

                do
                {
                    long PacketSize = 0;

                    if (TempLengthOfFile % bufferSize != TempLengthOfFile)
                    {
                        TotalBytesSent = TotalBytesSent + bufferSize;
                        TempLengthOfFile = TempLengthOfFile - bufferSize;
                        PacketSize = bufferSize;
                    }
                    else if (TempLengthOfFile % bufferSize == TempLengthOfFile)
                    {
                        TotalBytesSent = TotalBytesSent + TempLengthOfFile;
                        PacketSize = TempLengthOfFile;
                    }

                    PacketNumber++;

                    ProtocolMessage.sendMessage(clientSocket, "$FRANK,DOWNLOAD," + PacketNumber + "," + PacketNumber + ",");
                    //wait until an ok comes from the client then send
                    bool running = true;
                    while (running)
                    {
                        if (ProtocolMessage.recMess(clientSocket) == "$FRANK,DOWNLOAD,OK,")
                        {
                            running = false;
                        }
                    }

                    // in the Sending State

                    FileStream filedata = new FileStream(options["Projects_Path"] + Filename, FileMode.Open, FileAccess.Read);
                    buffer = new byte[bufferSize];

                    int count;
                    

                    while ((count = filedata.Read(buffer, 0, bufferSize)) > 0)
                    {
                        clientSocket.Send(buffer);


                        
                        if (ProtocolMessage.recMess(clientSocket) == "$FRANK,DOWNLOAD,BAD,")
                        {
                            Thread.Sleep(100);
                            clientSocket.Send(buffer);
                        }
                    }


                    //Send_Builder(PacketNumber, PacketSize);

                } while (TotalBytesSent != fileinfo.Length);

            }
        }



        private bool data(string[] message)
        {

            if (message[2] == "UPLOAD")
            {
                fileMan.addfile(message[3], message[4], message[5]);

                FileStream filedata = new FileStream(options["Projects_Path"] + "\\" + message[3], FileMode.Append, FileAccess.Write);
                Thread.Sleep(100);

                int receivedBytesLen = 1;
                bool uploading = true;
                do
                {
                    Thread.Sleep(100);
                    receivedBytesLen = clientSocket.Receive(buffer);
                    if (receivedBytesLen != bufferSize)
                    {
                        System.Diagnostics.Debug.WriteLine(receivedBytesLen);
                    }

                    filedata.Write(buffer, 0, bufferSize);

                    Thread.Sleep(10);

                    if (receivedBytesLen == 0)
                    {
                        uploading = false;
                        Thread.Sleep(10);
                    }
                    Thread.Sleep(10);

                } while (uploading == true);

                System.Diagnostics.Debug.WriteLine("Completed");
                filedata.Flush();
                filedata.Close();

            }
            else if (message[2] == "DOWNLOAD")
            {
                FileStream filedata = new FileStream(options["Projects_Path"] + message[3], FileMode.Open, FileAccess.Read);

                buffer = new byte[bufferSize];

                int count;


                while ((count = filedata.Read(buffer, 0, bufferSize)) > 0)
                {
                    Thread.Sleep(1000);
                    System.Diagnostics.Debug.WriteLine(" " + clientSocket.Send(buffer, count, SocketFlags.None));
                }

                System.Diagnostics.Debug.WriteLine("file: " + message[3] + " has been sent");
            }
            else if (message[3] == "LIST")
            {
                //fileMan.
            }

            return true;
        }

        private void SendData(string[] Message)
        {

        }
    }
}

